-- -------------------------------------------------------------------------
-- Features/Weapon.lua (Weapon Features)
-- Direct Lexis API usage with ClickUI notification system
-- -------------------------------------------------------------------------

local module = {}

-- [Lua 5.4] <const> for function references
local pcall <const> = pcall
local ipairs <const> = ipairs
local pairs <const> = pairs
local type <const> = type
local tostring <const> = tostring

-- [Dependencies]
local ui = nil
local notification = nil
local features_config = nil

local function _T(text)
    if _G and _G._T then
        return _G._T(text)
    end
    return text
end

-- Module name for config storage
local MODULE_NAME <const> = "Weapon"

-- =========================================================================
-- [Constants]
-- =========================================================================

local WEAPON_HASHES = {
    -- Pistols
    { name = "Pistol", hash = "WEAPON_PISTOL" },
    { name = "Combat Pistol", hash = "WEAPON_COMBATPISTOL" },
    { name = "AP Pistol", hash = "WEAPON_APPISTOL" },
    { name = "Heavy Pistol", hash = "WEAPON_HEAVYPISTOL" },
    -- SMGs
    { name = "Micro SMG", hash = "WEAPON_MICROSMG" },
    { name = "SMG", hash = "WEAPON_SMG" },
    { name = "Assault SMG", hash = "WEAPON_ASSAULTSMG" },
    -- Rifles
    { name = "Assault Rifle", hash = "WEAPON_ASSAULTRIFLE" },
    { name = "Carbine Rifle", hash = "WEAPON_CARBINERIFLE" },
    { name = "Advanced Rifle", hash = "WEAPON_ADVANCEDRIFLE" },
    { name = "Special Carbine", hash = "WEAPON_SPECIALCARBINE" },
    -- Shotguns
    { name = "Pump Shotgun", hash = "WEAPON_PUMPSHOTGUN" },
    { name = "Sawed-Off Shotgun", hash = "WEAPON_SAWNOFFSHOTGUN" },
    { name = "Assault Shotgun", hash = "WEAPON_ASSAULTSHOTGUN" },
    -- Snipers
    { name = "Sniper Rifle", hash = "WEAPON_SNIPERRIFLE" },
    { name = "Heavy Sniper", hash = "WEAPON_HEAVYSNIPER" },
    -- Heavy
    { name = "RPG", hash = "WEAPON_RPG" },
    { name = "Grenade Launcher", hash = "WEAPON_GRENADELAUNCHER" },
    { name = "Minigun", hash = "WEAPON_MINIGUN" },
    -- Melee
    { name = "Knife", hash = "WEAPON_KNIFE" },
    { name = "Baseball Bat", hash = "WEAPON_BAT" },
    { name = "Crowbar", hash = "WEAPON_CROWBAR" }
}

local PISTOLS = { "WEAPON_PISTOL", "WEAPON_COMBATPISTOL", "WEAPON_APPISTOL", "WEAPON_HEAVYPISTOL" }
local RIFLES = { "WEAPON_ASSAULTRIFLE", "WEAPON_CARBINERIFLE", "WEAPON_ADVANCEDRIFLE", "WEAPON_SPECIALCARBINE" }
local HEAVY = { "WEAPON_RPG", "WEAPON_GRENADELAUNCHER", "WEAPON_MINIGUN" }

local AMMO_AMOUNT = 9999
local DAMAGE_MIN, DAMAGE_MAX, DAMAGE_DEFAULT, DAMAGE_STEP = 1.0, 10.0, 1.0, 0.5

-- [State]
local state = {
    subtab_idx = 1,
    -- Weapon options
    infinite_ammo = false,
    -- Multipliers
    damage_multiplier = DAMAGE_DEFAULT,
    -- Cache
    last_infinite_ammo = false,
    last_damage = nil,
    last_weapon_hash = 0,
    infinite_ammo_weapons = {}
}

-- -------------------------------------------------------------------------
-- Helper Functions
-- -------------------------------------------------------------------------

local function show_notify(msg, type_str)
    if notification and notification.notify then
        notification.notify(msg, type_str)
    end
end

local function get_me()
    if not players or not players.me then return nil end
    local ok, me = pcall(players.me)
    if not ok or not me then return nil end
    return me
end

local function get_ped()
    local me = get_me()
    return me and me.ped
end

local function call_native(hash, ...)
    if not invoker or not invoker.call then return nil end
    local ok, result = pcall(invoker.call, hash, ...)
    if ok then return result end
    return nil
end

local hash_cache = {}
local function get_hash(name)
    local cached = hash_cache[name]
    if cached ~= nil then return cached end
    if not joaat then return 0 end
    local ok, hash = pcall(joaat, name)
    if ok and type(hash) == "number" then
        hash_cache[name] = hash
        return hash
    end
    return 0
end

-- -------------------------------------------------------------------------
-- Weapon Actions
-- -------------------------------------------------------------------------

local function give_weapons(weapon_list)
    local ped = get_ped()
    if not ped or ped == 0 then
        show_notify(_T("Invalid player ped"), "Error")
        return 0
    end

    local count = 0
    local GIVE_WEAPON = get_hash("GIVE_WEAPON_TO_PED")

    for _, hash_name in ipairs(weapon_list) do
        local weapon_hash = get_hash(hash_name)
        if weapon_hash ~= 0 then
            call_native(GIVE_WEAPON, ped, weapon_hash, AMMO_AMOUNT, false, true)
            count = count + 1
        end
    end

    return count
end

local function give_all_weapons()
    local list = {}
    for _, w in ipairs(WEAPON_HASHES) do
        list[#list + 1] = w.hash
    end
    local count = give_weapons(list)
    show_notify(string.format(_T("Weapons given: %s"), tostring(count)), "Success")
end

local function remove_all_weapons()
    local ped = get_ped()
    if not ped or ped == 0 then
        show_notify(_T("Invalid player ped"), "Error")
        return
    end

    local REMOVE_WEAPONS = get_hash("REMOVE_ALL_PED_WEAPONS")
    call_native(REMOVE_WEAPONS, ped, true)
    show_notify(_T("All weapons removed"), "Success")
end

local function max_ammo_all()
    local ped = get_ped()
    if not ped or ped == 0 then
        show_notify(_T("Invalid player ped"), "Error")
        return
    end

    local count = 0
    local ADD_AMMO = get_hash("ADD_AMMO_TO_PED")

    for _, w in ipairs(WEAPON_HASHES) do
        local weapon_hash = get_hash(w.hash)
        if weapon_hash ~= 0 then
            call_native(ADD_AMMO, ped, weapon_hash, AMMO_AMOUNT)
            count = count + 1
        end
    end

    show_notify(string.format(_T("Ammo added to %s weapons"), tostring(count)), "Success")
end

-- -------------------------------------------------------------------------
-- Config Save/Load Helpers
-- -------------------------------------------------------------------------

local function load_config()
    if not features_config then return end
    local saved = features_config.get_module(MODULE_NAME)
    if not saved then return end
    if saved.infinite_ammo ~= nil then state.infinite_ammo = saved.infinite_ammo end
    if saved.damage_multiplier ~= nil then state.damage_multiplier = saved.damage_multiplier end
end

local function save_config()
    if not features_config then return end
    features_config.set_module(MODULE_NAME, {
        infinite_ammo = state.infinite_ammo,
        damage_multiplier = state.damage_multiplier
    }, true)
end

-- -------------------------------------------------------------------------
-- Module Interface
-- -------------------------------------------------------------------------

function module.init(u, _, _, _, _, _, _)
    ui = u
    notification = require("ClickUl.UI.notification")
    local ok, fc = pcall(require, "ClickUl.Config.features")
    if ok and fc then features_config = fc end
    state.infinite_ammo_weapons = {}
    state.last_damage = nil
    load_config()
end

function module.on_tick()
    local me = get_me()
    local ped = me and me.ped
    if not ped or ped == 0 then return end

    local player_id = (me and me.id) or 0

    -- Native hashes
    local SET_INFINITE_AMMO = get_hash("SET_PED_INFINITE_AMMO")
    local SET_INFINITE_CLIP = get_hash("SET_PED_INFINITE_AMMO_CLIP")
    local GET_SELECTED_WEAPON = get_hash("GET_SELECTED_PED_WEAPON")
    local SET_DAMAGE_MOD = get_hash("SET_PLAYER_WEAPON_DAMAGE_MODIFIER")
    local SET_MELEE_MOD = get_hash("SET_PLAYER_MELEE_WEAPON_DAMAGE_MODIFIER")

    -- 1. Infinite Ammo
    if state.infinite_ammo then
        if GET_SELECTED_WEAPON == 0 then return end
        local result = call_native(GET_SELECTED_WEAPON, ped)
        local weapon_hash = result and result.int or 0

        if not state.last_infinite_ammo or state.last_weapon_hash ~= weapon_hash then
            if weapon_hash ~= 0 then
                if SET_INFINITE_AMMO ~= 0 then
                    call_native(SET_INFINITE_AMMO, ped, true, weapon_hash)
                end
                state.infinite_ammo_weapons[weapon_hash] = true
            end
            if SET_INFINITE_CLIP ~= 0 then
                call_native(SET_INFINITE_CLIP, ped, true)
            end
            state.last_infinite_ammo = true
            state.last_weapon_hash = weapon_hash
        end
    elseif state.last_infinite_ammo then
        if SET_INFINITE_AMMO ~= 0 then
            for hash in pairs(state.infinite_ammo_weapons) do
                if type(hash) == "number" and hash ~= 0 then
                    call_native(SET_INFINITE_AMMO, ped, false, hash)
                end
            end
        end
        state.infinite_ammo_weapons = {}
        if SET_INFINITE_CLIP ~= 0 then
            call_native(SET_INFINITE_CLIP, ped, false)
        end
        state.last_infinite_ammo = false
        state.last_weapon_hash = 0
    end

    -- 2. Damage Multiplier
    if state.damage_multiplier ~= state.last_damage then
        if SET_DAMAGE_MOD ~= 0 then
            call_native(SET_DAMAGE_MOD, player_id, state.damage_multiplier)
        end
        if SET_MELEE_MOD ~= 0 then
            call_native(SET_MELEE_MOD, player_id, state.damage_multiplier)
        end
        state.last_damage = state.damage_multiplier
    end
end

function module.draw()
    state.subtab_idx = ui.SubTabBar({ _T("Weapons"), _T("Mods") }, state.subtab_idx or 1)

    -- TAB 1: Weapons
    if state.subtab_idx == 1 then
        ui.DualColumn(
            function()
                ui.Group(_T("Weapon Management"), function()
                    if ui.Button(_T("Give All Weapons")) then
                        give_all_weapons()
                    end

                    if ui.Button(_T("Remove All Weapons")) then
                        remove_all_weapons()
                    end

                    if ui.Button(_T("Max Ammo All")) then
                        max_ammo_all()
                    end
                end)

                ui.Group(_T("Ammo Options"), function()
                    state.infinite_ammo = ui.Checkbox(_T("Infinite Ammo"), state.infinite_ammo)
                end)
            end,
            function()
                ui.Group(_T("Quick Weapon Sets"), function()
                    if ui.Button(_T("Give All Pistols")) then
                        local count = give_weapons(PISTOLS)
                        show_notify(string.format(_T("Pistols given: %s"), tostring(count)), "Success")
                    end

                    if ui.Button(_T("Give All Rifles")) then
                        local count = give_weapons(RIFLES)
                        show_notify(string.format(_T("Rifles given: %s"), tostring(count)), "Success")
                    end

                    if ui.Button(_T("Give Heavy Weapons")) then
                        local count = give_weapons(HEAVY)
                        show_notify(string.format(_T("Heavy weapons given: %s"), tostring(count)), "Success")
                    end
                end)
            end
        )

    -- TAB 2: Mods
    elseif state.subtab_idx == 2 then
        ui.DualColumn(
            function()
                ui.Group(_T("Damage Modifier"), function()
                    state.damage_multiplier = ui.Slider(
                        _T("Damage Multiplier"),
                        state.damage_multiplier,
                        DAMAGE_MIN,
                        DAMAGE_MAX,
                        DAMAGE_STEP
                    )

                    if ui.Button(_T("Reset Damage (1.0x)")) then
                        state.damage_multiplier = DAMAGE_DEFAULT
                        show_notify(_T("Damage reset to 1.0x"), "Info")
                    end
                end)
            end,
            function()
                ui.Group(_T("Advanced Modifications"), function()
                    ui.Button(_T("Coming Soon"))
                end)
            end
        )
    end
end

function module.on_menu_close()
    save_config()
end

return module
